﻿
using EmperialApps.WeatherSpark.Data;
using Microsoft.WindowsAzure.Storage;
using Microsoft.WindowsAzure.Storage.Table;
using System.Collections.Generic;
using System.Diagnostics;

namespace EmperialApps.WeatherSpark.Service.Internal {

    /// <summary>Acts as a storage and retrieval system for forecast information, backed by an Azure table container.</summary>
    internal sealed class ForecastInfoTableStore {

        private const string ForecastInfoTableName = "forecastinfo";

        private readonly CloudTable _table;


        /// <summary>Initializes a new instance of the <see cref="ForecastInfoTableStore"/> class.</summary>
        public ForecastInfoTableStore( CloudStorageAccount account ) {
            var client = account.CreateCloudTableClient( );
            this._table = client.GetTableReference( ForecastInfoTableName );
            bool created = this._table.CreateIfNotExists( );
        }


        /// <summary>Adds forecast information to the table.</summary>
        public void Add( ForecastInfo info ) {
            var operation = TableOperation.InsertOrMerge( info );
            try {
                var response = this._table.Execute( operation );
                response.Trace( "Adding", typeof( ForecastInfo ) );
            }
            catch( StorageException ex ) {
                ex.Trace( "Could not add forecast info for " + info );
            }
        }

        /// <summary>Updates an existing forecast info in the table.</summary>
        public bool Update( ForecastInfo info ) {
            // Search for an existing matching info.
            var existingForecastInfo = this._table.Retrieve( info );

            // If the info has a different URL or request time, update it.
            bool update = ForecastInfo.Update( existingForecastInfo, info );
            if( update ) {
                var operation = TableOperation.Replace( existingForecastInfo );
                try {
                    var response = this._table.Execute( operation );
                    response.Trace( "Updating", typeof( ForecastInfo ) );
                }
                catch( StorageException ex ) {
                    if( ex.Message.Contains( "(412)" ) )
                        TraceEventType.Verbose.Trace( "Conflict updating " + existingForecastInfo );
                    else
                        ex.Trace( "Could not update forecast info for " + existingForecastInfo );
                }
            }

            return update;
        }

        /// <summary>Gets the forecast information for the specified location.</summary>
        public ForecastInfo Get( Coordinate location ) {
            var target = new ForecastInfo( location );

            return this._table.Retrieve( target );
        }

        /// <summary>Gets forecast information for all saved location.</summary>
        public IEnumerable<ForecastInfo> Get( ) {
            var query = new TableQuery<ForecastInfo>( );
            return this._table.ExecuteQuery( query );
        }

    }

}
